<template>
  <div class="virtual-scroll-list" ref="containerRef" @scroll="handleScroll">
    <div class="scroll-content" :style="{ height: `${totalHeight}px` }">
      <div
        class="visible-items"
        :style="{ transform: `translateY(${visibleRange.offsetY}px)` }"
      >
        <div
          v-for="item in visibleItems"
          :key="item.id"
          class="virtual-item"
          :style="{ height: `${itemHeight}px` }"
        >
          <slot :item="item" :index="item.index" />
        </div>
      </div>
    </div>
    
    <!-- 加载更多指示器 -->
    <div v-if="loading" class="loading-indicator">
      <el-icon class="is-loading"><Loading /></el-icon>
      <span>加载中...</span>
    </div>
    
    <!-- 无更多数据提示 -->
    <div v-if="!hasMore && items.length > 0" class="no-more-indicator">
      <span>没有更多数据了</span>
    </div>
    
    <!-- 空状态 -->
    <div v-if="!loading && items.length === 0" class="empty-state">
      <slot name="empty">
        <el-empty description="暂无数据" />
      </slot>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { Loading } from '@element-plus/icons-vue'
import { useVirtualScroll } from '../composables/useVirtualScroll'

interface VirtualScrollItem {
  id: string | number
  [key: string]: any
}

interface Props {
  items: VirtualScrollItem[]
  itemHeight: number
  containerHeight?: number
  buffer?: number
  loading?: boolean
  hasMore?: boolean
  loadThreshold?: number
}

interface Emits {
  (e: 'load-more'): void
  (e: 'scroll', scrollTop: number): void
}

const props = withDefaults(defineProps<Props>(), {
  containerHeight: 400,
  buffer: 5,
  loading: false,
  hasMore: true,
  loadThreshold: 0.8
})

const emit = defineEmits<Emits>()

const {
  containerRef,
  scrollTop,
  totalHeight,
  visibleItems,
  visibleRange,
  isNearBottom,
  handleScroll: handleVirtualScroll,
  scrollToItem,
  scrollToTop,
  scrollToBottom
} = useVirtualScroll(props.items, {
  itemHeight: props.itemHeight,
  containerHeight: props.containerHeight,
  buffer: props.buffer,
  threshold: props.loadThreshold
})

// 处理滚动事件
const handleScroll = (event: Event) => {
  handleVirtualScroll(event)
  emit('scroll', scrollTop.value)
  
  // 检查是否需要加载更多
  if (isNearBottom.value && props.hasMore && !props.loading) {
    emit('load-more')
  }
}

// 暴露方法给父组件
defineExpose({
  scrollToItem,
  scrollToTop,
  scrollToBottom,
  scrollTop: computed(() => scrollTop.value)
})
</script>

<style scoped>
.virtual-scroll-list {
  height: 100%;
  overflow-y: auto;
  position: relative;
}

.scroll-content {
  position: relative;
  width: 100%;
}

.visible-items {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
}

.virtual-item {
  width: 100%;
  box-sizing: border-box;
}

.loading-indicator {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 16px;
  color: var(--el-text-color-regular);
  font-size: 14px;
}

.no-more-indicator {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  color: var(--el-text-color-placeholder);
  font-size: 13px;
}

.empty-state {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  min-height: 200px;
}

/* 滚动条样式 */
.virtual-scroll-list::-webkit-scrollbar {
  width: 6px;
}

.virtual-scroll-list::-webkit-scrollbar-track {
  background: var(--el-border-color-lighter);
  border-radius: 3px;
}

.virtual-scroll-list::-webkit-scrollbar-thumb {
  background: var(--el-border-color);
  border-radius: 3px;
}

.virtual-scroll-list::-webkit-scrollbar-thumb:hover {
  background: var(--el-border-color-dark);
}
</style>